Upgrade WorkOS to v8, fix public auth handler socket reuse - #134
Merged
Conversation
- Upgrade @workos-inc/node to v8 and switch to the worker subpath
import (`@workos-inc/node/worker`). The v8 worker build ships with a
clean `iron-webcrypto` dependency, so the `require('buffer/index.js')`
patch is no longer needed and gets deleted.
- Fix "Cannot perform I/O on behalf of a different request" on the
second login after logout. `HttpApiBuilder.toWebHandler` was called
once at module load for the public auth handler, which memoized
`DbService.Live`'s `Layer.scoped` — the `sql` connection was created
in the module scope and reused across requests. workerd tears down
TCP sockets at request boundaries, so the second request hit a dead
socket. Build the public handler per-request and dispose it after.
- Scrub internal details from tagged error response payloads. The
`UserStoreError`/`WorkOSError` schemas had a `cause: Schema.Unknown`
field which encoded the full drizzle/workos error (SQL, params,
stack) into 500 response bodies. Drop the field, set a 500 status
annotation, and log the real cause server-side via `console.error`
so we can see it in logs without leaking it to clients.
- Add a `memberships` table to the cloud schema as the foundation for
multi-workspace support (one account → many orgs) per notes/auth.md.
Migration regenerated since prod was wiped and reseeded.
- Rename `APP_URL` → `VITE_PUBLIC_SITE_URL` for consistency with the
public site URL naming used elsewhere. Used in the auth login
handler to compute the redirect origin instead of trusting the
request's Host header (which points at the internal proxy target
in dev).
- Tighten `secure: true` on session cookies unconditionally.
- Kill the `POST /auth/organization` standalone endpoint. The only
place orgs are created is the auth callback, which auto-provisions
a default workspace on first login.
The v8 upgrade, per-request handler, VITE_PUBLIC_SITE_URL rename, and
`secure: true` changes are cherry-picks / adaptations from PR #133.
Co-authored-by: Saatvik Arya <aryasaatvik@gmail.com>
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
executor-cloud | 283b061 | Apr 09 2026, 08:22 PM |
3 tasks
RhysSullivan
added a commit
that referenced
this pull request
May 31, 2026
- Upgrade @workos-inc/node to v8 and switch to the worker subpath
import (`@workos-inc/node/worker`). The v8 worker build ships with a
clean `iron-webcrypto` dependency, so the `require('buffer/index.js')`
patch is no longer needed and gets deleted.
- Fix "Cannot perform I/O on behalf of a different request" on the
second login after logout. `HttpApiBuilder.toWebHandler` was called
once at module load for the public auth handler, which memoized
`DbService.Live`'s `Layer.scoped` — the `sql` connection was created
in the module scope and reused across requests. workerd tears down
TCP sockets at request boundaries, so the second request hit a dead
socket. Build the public handler per-request and dispose it after.
- Scrub internal details from tagged error response payloads. The
`UserStoreError`/`WorkOSError` schemas had a `cause: Schema.Unknown`
field which encoded the full drizzle/workos error (SQL, params,
stack) into 500 response bodies. Drop the field, set a 500 status
annotation, and log the real cause server-side via `console.error`
so we can see it in logs without leaking it to clients.
- Add a `memberships` table to the cloud schema as the foundation for
multi-workspace support (one account → many orgs) per notes/auth.md.
Migration regenerated since prod was wiped and reseeded.
- Rename `APP_URL` → `VITE_PUBLIC_SITE_URL` for consistency with the
public site URL naming used elsewhere. Used in the auth login
handler to compute the redirect origin instead of trusting the
request's Host header (which points at the internal proxy target
in dev).
- Tighten `secure: true` on session cookies unconditionally.
- Kill the `POST /auth/organization` standalone endpoint. The only
place orgs are created is the auth callback, which auto-provisions
a default workspace on first login.
The v8 upgrade, per-request handler, VITE_PUBLIC_SITE_URL rename, and
`secure: true` changes are cherry-picks / adaptations from PR #133.
Co-authored-by: Saatvik Arya <aryasaatvik@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
@workos-inc/nodeto v8 and switch to the worker subpath import (@workos-inc/node/worker). The v8 worker build ships with a cleaniron-webcrypto, so therequire('buffer/index.js')patch is deleted.HttpApiBuilder.toWebHandlerwas called once at module load for the public auth handler, which memoizedDbService.Live'sLayer.scoped— thesqlconnection was created in the module scope and reused across requests. workerd tears down TCP sockets at request boundaries, so the second request hit a dead socket. Build the public handler per-request and dispose it after.UserStoreError/WorkOSErrorhad acause: Schema.Unknownfield which encoded the full drizzle/workos error (SQL, params, stack) into 500 responses. Drop the field, annotate 500 status, log the real cause server-side.membershipstable to the cloud schema as the foundation for multi-workspace support (one account → many orgs) per `notes/auth.md`. Migration regenerated since prod was wiped and reseeded.The v8 upgrade, per-request public handler, `VITE_PUBLIC_SITE_URL` rename, and `secure: true` changes are cherry-picks / adaptations from #133 — credit to @aryasaatvik for diagnosing the socket reuse bug.
Test plan